#region Namespace Declarations

using System;

#endregion Namespace Declarations

namespace RSEngine.Math
{

    /// <summary>
    /// 2 dimensional vector.
    /// </summary>
    //[StructLayout(LayoutKind.Sequential)]
    public struct Vector2
    {

        #region Variables

        public float x, y;

        private static readonly Vector2 invalidVector = new Vector2(float.NaN, float.NaN);

        #endregion Fields

        #region Constructors

        public Vector2(float x, float y)
        {
            this.x = x;
            this.y = y;
        }

        #endregion Constructors

        #region Properties

        public static Vector2 Invalid
        {
            get
            {
                return invalidVector;
            }
        }

        public bool IsInvalid
        {
            get
            {
                return Double.IsNaN(x) || Double.IsNaN(y);
            }
        }

        #endregion

        #region Operators

        public static bool operator ==(Vector2 left, Vector2 right)
        {
            return left.x == right.x && left.y == right.y;
        }

        public static bool operator !=(Vector2 left, Vector2 right)
        {
            return left.x != right.x || left.y != right.y;
        }

        /// <summary>
        ///	Used when a Vector2 is added to another Vector2.
        /// </summary>
        public static Vector2 operator +(Vector2 left, Vector2 right)
        {
            return new Vector2(left.x + right.x, left.y + right.y);
        }

        /// <summary>
        ///	Used to subtract a Vector2 from another Vector2.
        /// </summary>
        public static Vector2 operator -(Vector2 left, Vector2 right)
        {
            return new Vector2(left.x - right.x, left.y - right.y);
        }

        /// <summary>
        ///	Used when a Vector2 is multiplied by a scalar value.
        /// </summary>
        public static Vector2 operator *(Vector2 left, float scalar)
        {
            return new Vector2(left.x * scalar, left.y * scalar);
        }

        /// <summary>
        ///	Used when a scalar value is multiplied by a Vector2.
        /// </summary>
        public static Vector2 operator *(float scalar, Vector2 right)
        {
            return new Vector2(right.x * scalar, right.y * scalar);
        }

        /// <summary>
        ///	Used to negate the elements of a vector.
        /// </summary>
        public static Vector2 operator -(Vector2 left)
        {
            return new Vector2(-left.x, -left.y);
        }

        #endregion

        #region Clone

        public Vector2 Clone()
        {
            Vector2 clone = new Vector2();
            clone.x = x;
            clone.y = y;
            return clone;
        }

        #endregion

        #region Misc

        public override string ToString()
        {
            return string.Format("Vector2({0}, {1})", this.x, this.y);
        }

        public override bool Equals(object obj)
        {
            return obj is Vector2 && this == (Vector2)obj;
        }

        public override int GetHashCode()
        {
            return x.GetHashCode() ^ y.GetHashCode();
        }

        #endregion

    }

}
